package com.ns.sbs.oauth.rent.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ns.basic.server.bo.PermissionBO;
import com.ns.basic.server.service.IServerService;
import com.ns.core.annotations.ReqLog;
import com.ns.core.current.config.SysConst;
import com.ns.core.utils.StpUtil;
import com.ns.core.utils.sg.ResultError;
import com.ns.core.utils.sg.ResultOk;
import com.ns.core.vo.bs.BasicTreeVO;
import com.ns.sbs.oauth.acc.entry.Account;
import com.ns.sbs.oauth.acc.service.IAccountService;
import com.ns.sbs.oauth.acc4auth.service.IAccPasswordService;
import com.ns.sbs.oauth.cur.AuthTreeVO;
import com.ns.sbs.oauth.menu.service.IMenuService;
import com.ns.sbs.oauth.rent.bo.RentBO;
import com.ns.sbs.oauth.rent.bo.RentPageBO;
import com.ns.sbs.oauth.rent.dto.RentPageDto;
import com.ns.sbs.oauth.rent.dto.RentPermissionDto;
import com.ns.sbs.oauth.rent.entry.RentEntry;
import com.ns.sbs.oauth.rent.service.IRentPermissionService;
import com.ns.sbs.oauth.rent.service.IRentServerService;
import com.ns.sbs.oauth.rent.service.IRentService;
import com.ns.sbs.oauth.rent.vo.RentEntryVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 租户业务相关操作
 *
 * @author lw
 */
@RestController
@RequestMapping("/rent/")
@RequiredArgsConstructor
@CrossOrigin
public class RentController {

    private final IRentService rentService;

    private final IRentServerService rentServerService;

    private final IServerService serverService;

    private final IMenuService menuService;

    private final IRentPermissionService rentPermissionService;

    private final IAccountService adminService;

    private final IAccPasswordService adminPasswordService;

    /**
     * 增
     *
     * @param bo 参数
     */
    @PostMapping("add")
    @ReqLog(module = "租户", name = "增", isRecordFlag = true)
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ResultOk add(@RequestBody RentBO bo) {
        RentEntry rent = new RentEntry();
        BeanUtils.copyProperties(bo, rent);
        rent.setSort(rentService.count() + 1);
        rentService.saveOrUpdate(rent);
        // 创建默认管理员用户
        Long exist = adminService.checkByPhone(rent.getPhone());
        if (Objects.nonNull(exist) && exist > 0) {
            throw new ResultError("该手机号【" + rent.getPhone() + "】已被占用");
        }
        // 如果权限为空，则不进行初始化初始化用户
        Account acc = new Account();
        acc.setPhone(rent.getPhone());
        acc.setName(rent.getPhone());
        acc.setNickName(rent.getName());
        acc.setRid(rent.getId());
        acc.setCreator(StpUtil.getLoginUserId());
        acc.setAvatar(null);
        acc.setLoginCount(null);
        acc.setLoginIp(null);
        acc.setLoginTime(null);
        if (adminService.save(acc)) {
            // 默认密码（md5与明文）
            adminPasswordService.updatePassword(acc.getId(), rent.getPhone());
        }
        // 更新租户中的默认用户
        rent.setAccId(acc.getId());
        return ResultOk.getByBoolean(rentService.updateById(rent));
    }


    /**
     * 改
     *
     * @param bo 参数
     */
    @PostMapping("update")
    @ReqLog(module = "租户", name = "改", isRecordFlag = true)
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ResultOk update(@RequestBody RentBO bo) {
        RentEntry rent = new RentEntry();
        BeanUtils.copyProperties(bo, rent);
        return ResultOk.getSuccessData(rentService.updateById(rent));
    }

    /**
     * 删
     *
     * @param id 参数
     */
    @GetMapping("delete")
    @ReqLog(module = "租户模块", name = "删", isRecordFlag = true)
    public ResultOk delete(Long id) {
        // 不能自己删除自己
        if (Objects.equals(StpUtil.getRid(), id)) {
            return ResultOk.getError("不能自己删除自己");
        }
        boolean rb = rentService.removeById(id);
        if (rb) {
            rentServerService.delByRid(id);
            rentPermissionService.removeById(id);
        }
        return ResultOk.getByBoolean(rb);
    }

    /**
     * 查询详情
     *
     * @param id 参数
     */
    @GetMapping("getById")
    @ReqLog(module = "租户模块", name = "详情")
    public ResultOk get(Long id) {
        RentEntry rent = rentService.getById(id);
        RentEntryVO reo = new RentEntryVO();
        BeanUtils.copyProperties(rent, reo);
        reo.setSids(rentServerService.getByRid(reo.getId()));
        return ResultOk.getSuccessData(reo);
    }

    /**
     * 查 - 集合
     */
    @PostMapping("getList")
    @ReqLog(module = "租户模块", name = "集合")
    public ResultOk getList(@RequestBody RentPageBO bo) {
        RentPageDto dto = new RentPageDto();
        BeanUtils.copyProperties(bo, dto);
        Page<RentEntryVO> page = rentService.getList(dto);
        return ResultOk.getPageData(page.getTotal(), page.getRecords());
    }

    /**
     * 查询分配 服务-菜单集合
     *
     * @param id 租户id
     */
    @GetMapping("menu/tree")
    @ReqLog(module = "租户模块", name = "服务-菜单：租户分配权限")
    public ResultOk getMenuTree(Long id) {
        AuthTreeVO tree = new AuthTreeVO();
        List<BasicTreeVO> stl = new ArrayList<>();
        try {
            Map<Long, String> server = serverService.selectServer();
            List<CompletableFuture<BasicTreeVO>> task = new ArrayList<>();
            for (Map.Entry<Long, String> sm : server.entrySet()) {
                BasicTreeVO vo = new BasicTreeVO();
                vo.setId(sm.getKey());
                vo.setName(sm.getValue());
                vo.setSort(Long.parseLong(String.valueOf(task.size())));
                CompletableFuture<BasicTreeVO> listCompletableFuture = CompletableFuture.supplyAsync(() -> {
                    List<BasicTreeVO> basicMenu = menuService.getMenuByMid(menuService.getServerMenus(sm.getKey()));
                    vo.setChildren(basicMenu);
                    return vo;
                });
                task.add(listCompletableFuture);
            }
            CompletableFuture.allOf(task.toArray(new CompletableFuture[0])).join();
            for (CompletableFuture<BasicTreeVO> taskFinish : task) {
                stl.add(taskFinish.get());
            }
            tree.setBt(stl);
            tree.setPermissions(rentService.getRentPermission(id));
        } catch (InterruptedException | NumberFormatException | ExecutionException e) {
            throw new ResultError("租户查询分配权限！");
        }
        return ResultOk.getSuccessData(tree);
    }

    /**
     * 分配租户菜单
     *
     * @param bo 参数
     */
    @PostMapping("assist")
    @ReqLog(module = "租户模块", name = "分配权限", isRecordFlag = true)
    @CacheEvict(cacheNames = SysConst.RENT_PERMISSION, key = "#bo.id")
    public ResultOk assist(@RequestBody PermissionBO bo) {
        if (Objects.isNull(bo.getPermissions())) {
            return ResultOk.getError("未知权限参数！");
        }
        if (Objects.isNull(bo.getId())) {
            return ResultOk.getError("未知租户参数！");
        }
        RentPermissionDto dto = new RentPermissionDto();
        BeanUtils.copyProperties(bo, dto);
        rentService.assistPermission(dto);
        return ResultOk.getSuccess();

    }
}
